/**
 * 应用的运行情景信息
 * 
 * 
 * + 切换到前台时的情景信息（使用的options参数）
 * + 页面加载时使用的情景信息（使用的query参数）
 * + 页面管理助手类等（规划中，该类用于判断当前页面是否可以通过“返回”或者下部导航回到首页；记录更多的历史页面栈信息）
 */
import store from "../../store/index";
import { JxbHttpClient } from "../session/session";
import PagePromoterUtil, { PagePromoter } from "./pagePromoter";
const Common = require('../../utils/common');

/**
 * 应用上下文信息操作类
 */
export default class AppSceneUtil {
    /**
     * 向全局注册应用切换至前台的情景信息
     * 
     * @param {{path: String, query: Object, scene: Number, shareTicket: String, referrer: {appId: string, extraData: Object}}} options App的onLaunch或onShow的回调参数
     * @returns {AppShowScene}
     */
    static registerAppShowScene(options) {
        let theScene = new AppShowScene(options)
        store.global('common.appScene.AppShowScene', theScene)
        return theScene
    }

    /**
     * 获取应用最近一次切换到前台时的场景信息
     * 
     * @returns {AppShowScene}
     */
    static getAppShowScene() {
        let theScene = store.global('common.appScene.AppShowScene')
        if (!(theScene instanceof AppShowScene)) {
            theScene = {}
        }
        return theScene
    }

    /**
     * 向全局注册页面加载的情景信息
     * 
     * @todo 由于App.onShow时获取不到页面的完整信息，需要在页面加载后将该信息补全。有些奇怪
     * @param {{}} page  页面信息，getCurrentPage[0]
     * @param {Boolean} fromOnLoadEvent 该方法的调用场景是否为页面的onLoad事件，true=是；false=其他事件
     * @returns {PageScene}
     */
    static setPageScene(page, fromOnLoadEvent = true) {
        let appScene = AppSceneUtil.getAppShowScene(),
            pageScene = new PageScene(page)
        appScene.setTheShowPageScene(pageScene, fromOnLoadEvent)
        console.debug('1. 向应用加载场景中补充缺失的首屏页面的加载场景: page',page, 'page scene',pageScene, 'app scene',appScene, 'from on load event', fromOnLoadEvent)
        return appScene
    }
}
/**
 * 应用被打开（展示）时的情景参数
 * 
 * 
 */
export class AppShowScene {
    /**
     * @private
     * @property {{_id: String, path: String, query: Object, scene: Number, shareTicket: String, referrer: {appId: string, extraData: Object}}}
     * @property {String} _data._id
     * @property {String} _data.needReportToServer 
     * @property {PageScene} _data.showPageScene
     */
    _data = {
        _id: '',
        needReportToServer: false,
        showPageScene: undefined,
        path: '',
        scene: 0
    }


    /**
     * app切换到前台时打开页面的加载场景信息（query信息）
     * 
     * @returns {PageScene}
     */
    getTheShowPageScene() {
        return this._data.showPageScene ? this._data.showPageScene : undefined
    }

    /**
     * 设置页面的加载场景
     * 
     * 场景信息不存在时才能切换
     * 
     * + `this._data.showPageScene`为`undefined`且`onLoadPage`为`true`时代表应用切换到前台并加载了新页面,可能的原因：`扫码/识别码`、`点击分享的内容`、`其他应用跳转进来`、`从小程序图标冷启动`等
     * + 如果`this._data.showPageScene为undefined`且`onLoadPage`为`false`时，表示应用切到前台但是没有加载页面，可能的原因是：`手机屏幕解锁`、`从手机的进程管理返回`、`因为分享等原因从其他应用界面返回`、`从小程序图标热启动`等
     * + 在这里我们认为`this._data.showPageScene`为`undefined`且`onLoadPage`为`true`时发生了从外部“链接”访问的情况，需要`上报该场景信息到服务器`、`判断是否需要切换顾问`等操作
     * 
     * @todo 由于App.onShow时获取不到页面的完整信息，需要在页面加载后将该信息补全。有些奇怪
     * @param {PageScene} thePageScene 
     * @param {Boolean} onLoadPage 该方法的调用场景是否为页面的onLoad事件，true=是；false=其他事件
     * @returns {this}
     */
    setTheShowPageScene(thePageScene, onLoadPage = true) {
        if (!this._data.showPageScene) {
            this._data.showPageScene = thePageScene
            if (onLoadPage) { // 页面加载时需要将信息上报到服务器
                console.debug('2.1 向服务器上报应用加载场景信息')
                this.markReportStatus(false)
                let pagePromoter = thePageScene.getThePromoter()
                PagePromoterUtil.registryPagePromoter(pagePromoter)
                if (pagePromoter.hasSharer()) {
                    console.debug('3.1 应用加载场景信息包括明确的推广来源信息')
                    // 有明确的推广来源时需要确认是否进行切换顾问的操作
                    Common.changeConsulant(pagePromoter.getTheSharer())
                }else{
                    console.debug('3.2 应用加载场景信息不包含明确的推广来源信息')
                }
                this.reportScene()
            }else{
                console.debug('2.2 非页面启动事件触发，页面场景信息被忽略')
            }
        } else {
            console.debug('2.3 应用加载场景已经补全首屏页面场景信息，页面场景信息被忽略')
        }
        return this
    }
    /**
     * 上报应用打开的场景信息
     * 
     * @method
     */
    reportScene() {
        this.markReportStatus(true)
        new Promise((resolve, reject) => {
            (new JxbHttpClient).request({
                url: 'AppMaster/Account/reportAppletScene',
                method: 'POST',
                data: {
                    scene: this.scene,
                    shareTicket: this.shareTicket,
                    referrerInfo: this.referrerInfo,
                    pagePath: this.getTheShowPageScene().route,
                    pageOptions: this.getTheShowPageScene().options,
                    promoter: this.getTheShowPageScene().getThePromoter().getQuery(true)
                }
            }).then(jxbResp => {

            }).catch(error => {
                this.markReportStatus(false)
            })
        })
    }

    /**
     * 当前场景信息是否需要上报给服务器
     */
    get needReportToServer() {
        return this._data.needReportToServer ? true : false
    }

    /**
     * 标记上报状态
     * 
     * @param {Boolean} reported true=已上报/无需上报；false=未上报/需要上报
     * @returns {this}
     */
    markReportStatus(reported = true) {
        this._data.needReportToServer = !reported
        return this
    }

    /**
     * app切换到前台时打开的页面路径
     * 
     * @returns {string}
     */
    get path() {
        return this._data.path
    }

    /**
     * 来源信息。从另一个小程序、公众号或 App 进入小程序时返回。否则返回 {}
     * 
     * + appId 来源小程序、公众号或 App 的 appId
     * + extraData 来源小程序传过来的数据，scene=1037或1038时支持
     * 
     * @return {{appId: string, extraData: Object}|{}}
     */
    get referrer() {
        // 兼容部分版本在无referrerInfo的时候会返回 undefined的情况
        return this._data.referrerInfo ? this._data.referrerInfo : {}
    }

    /**
     * 小程序切前台的场景值
     * 
     * @returns {Number}
     */
    get scene() {
        return parseInt(this._data.scene)
    }

    /**
     * 转发场景信息的获取凭据（票据）
     * 
     * 用于获取来源的转发记录
     * @returns {string}
     */
    get shareTicket() {
        return this._data.shareTicket
    }

    constructor(data) {
        if (typeof data !== 'object') {
            data = {}
        }
        this._data = data
    }
}

/**
 * 页面加载场景
 */
export class PageScene {
    /**
     * @private
     * @property {{}} _data
     * @property {String} _data.id
     * @property {String} _data.route
     * @property {{}} _data.options
     * @property {PagePromoter} _data.promoter
     */
    _data = {}
    get id() {
        return this._data.id
    }
    get route() {
        return this._data.route
    }
    get options() {
        return this._data.options
    }
    /**
     * 获取分享来源标识信息
     * 
     * @returns {PagePromoter}
     */
    getThePromoter() {
        if (!this._data.promoter) {
            this._data.promoter = new PagePromoter(this._data.route, this._data.options)
        }
        return this._data.promoter
    }
    /**
     * 带有推广信息
     * 
     * @returns {Boolean} true=有推广人信息
     */
    hasPromoter() {
        return this.getThePromoter().hasSharer()
    }
    /**
     * 构造指定页面（Page）的场景实例
     * 
     * @param {{options:{}, route:String, __wxExparserNodeId__:String}} page 
     */
    constructor(page) {
        let _data = {
            options: {},
            route: '',
            id: ''
        }
        if (typeof page === 'object' && typeof page.options === 'object') {
            _data.options = page.options ? page.options : {}
            _data.route = page.route ? page.route : ''
            _data.id = page.__wxExparserNodeId__ ? page.__wxExparserNodeId__ : JSON.stringify(page)
        }
        if (!_data.id) _data.id = JSON.stringify(page)
        this._data = _data
    }
}
